home *** CD-ROM | disk | FTP | other *** search
/ boe.pres.k12.wv.us / boe.pres.k12.wv.us.zip / boe.pres.k12.wv.us / Utilities / Xerox Workcentre 5335 / Windows Scan / 32-bit_x86 / Francais / cpsimage.cab / data / docio / xmldocutils.elf < prev    next >
Text File  |  2009-03-16  |  12KB  |  367 lines

  1. /*
  2. ** $Id: xmldocutils.elf,v 1.6 2008/02/13 16:01:13 campanel Exp $
  3. */
  4.  
  5. #load "sys/xipxml.elf";
  6.  
  7. /* Used by the scripted method below */
  8. /*
  9. private
  10. CLASS __Word {
  11.     METHOD compare( __Word left, __Word rite ) RETURNS( INTEGER result ) {
  12.         result = left.yb - rite.yb;
  13.     }
  14.  
  15.     INTEGER x0;
  16.     INTEGER x1;
  17.     INTEGER x0_min;
  18.     INTEGER x0_max;
  19.     INTEGER x1_min;
  20.     INTEGER x1_max;
  21.     INTEGER xw;
  22.     INTEGER yb;
  23.     INTEGER fs;
  24.     XmlElement ele;
  25. }
  26. */
  27.  
  28. /******************************************************************************/
  29. /*
  30. ** This class provides the ability to coalesce words into sentences while in
  31. ** the XIPXML format.
  32. */
  33. /* @New Creates a new instance of a XIPXML_COALESCEWORDS object. This object can be used to
  34.   progamatically access features of the language.
  35.   The xtol and ytol fields control the tolerence at which words will be joined. The
  36.   sw field controls the width of a space, also used to control when words will be
  37.   joined.
  38.  
  39.   // EXAMPLE's
  40.   #load "docio/xmldocutils.elf";
  41.  
  42.   STRING result = XIPXML_COALESCEWORDS.format( xipxml:input );
  43.  
  44.   // or
  45.  
  46.   XIPXML_COALESCEWORDS cw;
  47.  
  48.   cw.xtol = 14;  // more lose
  49.   cw.ytol = 6;
  50.   STRING result = cw.format( xipxml:input );
  51. */
  52. /* @format Coalesces words into sentences based on settings in the class. */
  53. CLASS XIPXML_COALESCEWORDS {
  54.     INTEGER ytol = 4;   /* y direction tolerance */
  55.     INTEGER xtol = 12;  /* x direction tolerance */
  56.     INTEGER sw = 16;    /* size of space */
  57.  
  58.     METHOD New () {}
  59.  
  60.     METHOD format( STRING xipxml ) RETURNS( STRING result ) NATIVE "XIPXML_CoalesceWords@documentio";
  61.  
  62.     /* This does the same as the native but is 20 times slower. */
  63.     /* Unless this algo needs to be customized, the native should
  64.     be used since this operation is done frequently. */
  65.     /*
  66.     METHOD format( STRING xipxml ) RETURNS( STRING result )
  67.     {
  68.         XmlDocumentBuilder db;
  69.         LIST lst;
  70.         INTEGER fnd, i, len;
  71.         STRING str, fs, fs_s;
  72.         __Word z, z_s;
  73.         XmlNode c;
  74.  
  75.         // Will be moving nodes around, suppress whitespace to make it look nicer
  76.         db.useOptions( opts:XmlDocumentBuilder.XML_PARSE_NOBLANKS );
  77.  
  78.         // Parse XML
  79.         XmlDocument d = db.parseString( doc:xipxml );
  80.         if( !d ) {
  81.             return;
  82.         }
  83.  
  84.         // Build list of Glyphs nodes
  85.         XmlNode root = d.getDocumentElement();
  86.         if( root.getNodeName() != "Page" ) {
  87.             return;
  88.         }
  89.  
  90.         for( c = root.getFirstChild(); c ; c = c.getNextSibling() ) {
  91.             if( c.getNodeName() == "Glyphs" ) {
  92.                 z = new(__Word);
  93.  
  94.                 z.ele = c;
  95.                 z.yb = z.ele.getAttribute( name:"yb" );
  96.                 z.x0 = z.ele.getAttribute( name:"x0" );
  97.                 z.xw = z.ele.getAttribute( name:"xw" );
  98.                 z.fs = z.ele.getAttribute( name:"famStyle" );
  99.                 z.x1 = z.x0 + z.xw;
  100.                 z.x1_min = z.x1 + this.sw - this.xtol;
  101.                 z.x1_max = z.x1 + this.sw + this.xtol;
  102.                 z.x0_min = z.x0 - this.sw - this.xtol;
  103.                 z.x0_max = z.x0 - this.sw + this.xtol;
  104.  
  105.                 lst.insert( obj:z );
  106.             }
  107.         }
  108.  
  109.         // Sort list based on y position
  110.         __Word wrd;
  111.         lst.sort( comparator:wrd);
  112.  
  113.         // Merge nodes based on position, removing merged nodes
  114.         for( fnd = 0; lst.length() != 0; fnd = 0 ) {
  115.             z = lst.ref( entry:0 );
  116.  
  117.             len = lst.length();
  118.             for( i = 1; i < len; i++ ) {
  119.                 z_s = lst.ref( entry:i );
  120.  
  121.                 if( (z_s.yb < (z.yb - this.ytol)) || (z_s.yb > (z.yb + this.ytol)) ) {
  122.                     break;
  123.                 }
  124.  
  125.                 if( z.fs != z_s.fs ) {
  126.                 } else if( (z_s.x0 >= z.x1_min) && (z_s.x0 <= z.x1_max) ) {
  127.                     str = z.ele.getAttribute( name:"str" ) + " " + z_s.ele.getAttribute( name:"str" );
  128.                     z.ele.setAttribute( name:"str", value:str );
  129.                     z.xw = z_s.x1 - z.x0;
  130.                     z.x1 = z.x0 + z.xw;
  131.                     z.x1_min = z.x1 + this.sw - this.xtol;
  132.                     z.x1_max = z.x1 + this.sw + this.xtol;
  133.                     str = z.xw;
  134.                     z.ele.setAttribute( name:"xw", value:str );
  135.  
  136.                     lst.remove( entry:i );
  137.                     root.removeChild( node:z_s.ele );
  138.                     fnd = 1;
  139.                     break;
  140.                 } else if( (z_s.x1 >= z.x0_min) && (z_s.x1 <= z.x0_max) ) {
  141.                     str = z_s.ele.getAttribute( name:"str" ) + " " + z.ele.getAttribute( name:"str" );
  142.                     z.ele.setAttribute( name:"str", value:str );
  143.                     z.x0 = z_s.x0;
  144.                     z.x0_min = z.x0 - this.sw - this.xtol;
  145.                     z.x0_max = z.x0 - this.sw + this.xtol;
  146.                     str = z.x0;
  147.                     z.ele.setAttribute( name:"x0", value:str );
  148.                     z.xw = z.x1 - z_s.x0;
  149.                     z.x1 = z.x0 + z.xw;
  150.                     z.x1_min = z.x1 + this.sw - this.xtol;
  151.                     z.x1_max = z.x1 + this.sw + this.xtol;
  152.                     str = z.xw;
  153.                     z.ele.setAttribute( name:"xw", value:str );
  154.  
  155.                     lst.remove( entry:i );
  156.                     root.removeChild( node:z_s.ele );
  157.                     fnd = 1;
  158.                     break;
  159.                 }
  160.             }
  161.  
  162.             if( !fnd ) {
  163.                 lst.remove( entry:0 );
  164.             }
  165.         }
  166.  
  167.         // Save XML
  168.         result = d.dumpString( format:1 );
  169.     }
  170.     */
  171. }
  172.  
  173.  
  174. /******************************************************************************/
  175. /*
  176. ** This class provides the a simple holder for statistics on a font. It is
  177. ** commonly used when laying out text in an XIPXML text layer.
  178. */
  179. /* @New Creates a new instance of a XIPXML_FONTSPEC object. This object is used
  180.   to provide statistics on a font when laying out text in an XIPXML text layer.
  181.  
  182.   // EXAMPLE's
  183.   #load "docio/xmldocutils.elf";
  184.  
  185.   XIPXML_FONTSPEC fs;
  186.   XIPXML_LAYER tl;
  187.  
  188.   fs.cellWidth = 20; // Make the EM cell be 20px by 20px
  189.   fs.cellHeight = 20;
  190.  
  191.   tl.addWord( str:"Hello World", x0:100, yb:100, font:fs );
  192. */
  193. CLASS XIPXML_FONTSPEC {
  194.     INTEGER cellWidth = 24;
  195.     INTEGER cellHeight = 24;
  196.     INTEGER famStyle = 0;
  197.     INTEGER interLineSpacing = 8;
  198.  
  199.     METHOD New() {}
  200. }
  201.  
  202.  
  203. /******************************************************************************/
  204. /*
  205. ** This class provides simple methods for adding text to an XIPXML text layer.
  206. */
  207. /* @New Creates a new instance of a XIPXML_LAYER object. This object is used
  208.   to add text to an XIPXML text layer.
  209.  
  210.   // EXAMPLE's
  211.   #load "docio/xmldocutils.elf";
  212.  
  213.   XIPXML_LAYER tl;
  214.   tl.loadLayer( img:img );    // Load the existing text layer from the XIPIMAGE
  215.  
  216.   XIPXML_FONTSPEC fs;
  217.  
  218.   fs.cellWidth = 20; // Make the EM cell be 20px by 20px
  219.   fs.cellHeight = 20;
  220.  
  221.   tl.addWord( str:"Hello World", x0:100, yb:100, font:fs );
  222.  
  223.   tl.saveLayer( img:img );    // Add or replace text layer on the XIPIMAGE
  224. */
  225. /* @loadLayer Extract and parse a text layer from an XIPIMAGE object. */
  226. /* @saveLayer Add or replace a text layer on an XIPIMAGE object. */
  227. /* @addGlyph Adds a raw glyph with a string and a bounding box. */
  228. /* @addWord Adds a simple word, or string, at the given (x0, yb) location. */
  229. /* @addTextBox Adds a box of text defined by a width and a starting location (x0, yb). It
  230.                uses a very simple layout only suitable for Western languages. */
  231. /* @addTextBoxByWords Adds a box of text defined by the number of words per line and
  232.                a starting location (x0, yb). It uses a very simple layout only
  233.                suitable for Western languages. */
  234. CLASS XIPXML_LAYER {
  235.     XmlDocument xml;    // private
  236.  
  237.     METHOD New()
  238.     {
  239.         XmlDocumentBuilder db;
  240.         this.xml = db.parseString( doc:"<Page xw=\"0\" yh=\"0\"/>");
  241.     }
  242.  
  243.     METHOD loadLayer( XIPIMAGE img )
  244.     {
  245.         XmlDocumentBuilder db;
  246.         INTEGER i, ltype, ttype;
  247.         STRING xipxml;
  248.  
  249.         // Find the text layer
  250.         if( img ) {
  251.             for( i = 0; i < img.nlayers; i++ ) {
  252.                 ltype = img.getMember( member:"layerType", num:i );
  253.                 ttype = img.getMember( member:"textType", num:i );
  254.                 if( (ltype == XIP_Text) && (ttype == XIP_XML_TEXT) ) {
  255.                     xipxml = img.getMember( num:i, member:"text" );
  256.                     break;
  257.                 }
  258.             }
  259.         }
  260.  
  261.         if( xipxml ) {
  262.             // Will be moving nodes around, suppress whitespace to make it look nicer
  263.             db.useOptions( opts:XmlDocumentBuilder.XML_PARSE_NOBLANKS );
  264.  
  265.             // Parse XML
  266.             this.xml = db.parseString( doc:xipxml );
  267.         }
  268.     }
  269.  
  270.     METHOD saveLayer( XIPIMAGE img )
  271.     {
  272.         // Save XML
  273.         STRING result = this.xml.dumpString( format:1 );
  274.         INTEGER i, ltype, ttype;
  275.  
  276.         // Find the text layer
  277.         if( img ) {
  278.             for( i = 0; i < img.nlayers; i++ ) {
  279.                 ltype = img.getMember( member:"layerType", num:i );
  280.                 ttype = img.getMember( member:"textType", num:i );
  281.                 if( (ltype == XIP_Text) && (ttype == XIP_XML_TEXT) ) {
  282.                     xipxml = img.setMember( num:i, member:"text", value:result );
  283.                     return;
  284.                 }
  285.             }
  286.  
  287.             // Add text layer
  288.             XIPLAYER layer = new( XIPLAYER, layerType:XIP_Text, visibility:FALSE );
  289.             img.addLayer( image:layer, ltype:XIP_Text, lindex:i );
  290.             img.setMember( num:i, member:"text", value:result );
  291.             img.setMember( num:i, member:"textType", value:XIP_XML_TEXT );
  292.         }
  293.     }
  294.  
  295.     METHOD addGlyph( STRING str, INTEGER x0, INTEGER yb, INTEGER wd, INTEGER ht, INTEGER famStyle )
  296.     {
  297.         XmlNode root = this.xml.getDocumentElement();
  298.         XmlElement ele = this.xml.createElement( name:"Glyphs" );
  299.         STRING s;
  300.  
  301.         ele.setAttribute( name:"str", value:str );
  302.         s = famStyle;
  303.         ele.setAttribute( name:"famStyle", value:s );
  304.         s = x0;
  305.         ele.setAttribute( name:"x0", value:s );
  306.         s = yb;
  307.         ele.setAttribute( name:"yb", value:s );
  308.         s = wd;
  309.         ele.setAttribute( name:"xw", value:s );
  310.         s = ht;
  311.         ele.setAttribute( name:"yh", value:s );
  312.  
  313.         root.appendChild( node:ele );
  314.     }
  315.  
  316.     METHOD addWord( STRING str, INTEGER x0, INTEGER yb, XIPXML_FONTSPEC font )
  317.     {
  318.         INTEGER wd;
  319.  
  320.         wd = str.length() * font.cellWidth;
  321.         this.addGlyph( str:str, x0:x0, yb:yb, wd:wd, ht:font.cellHeight, famStyle:font.famStyle );
  322.     }
  323.  
  324.     METHOD addTextBox( STRING str, INTEGER x0, INTEGER yb, INTEGER wd, XIPXML_FONTSPEC font )
  325.     {
  326.         INTEGER y = yb;
  327.         INTEGER x = x0;
  328.         INTEGER width;
  329.         LIST words = str.split( delims:" \t\n" );
  330.  
  331.         foreach( words:s ) {
  332.             width = s.length() * font.cellWidth;
  333.  
  334.             if( ((x + width) >= wd) && (x != x0) ) {
  335.                 x = x0;
  336.                 y += font.cellHeight + font.interLineSpacing;
  337.             }
  338.  
  339.             this.addGlyph( str:s, x0:x, yb:y, wd:width, ht:font.cellHeight, famStyle:font.famStyle );
  340.             x += width + font.cellWidth;
  341.         }
  342.     }
  343.  
  344.     METHOD addTextBoxByWords( STRING str, INTEGER x0, INTEGER yb, INTEGER wpl, XIPXML_FONTSPEC font )
  345.     {
  346.         INTEGER y = yb;
  347.         INTEGER x = x0;
  348.         INTEGER width;
  349.         INTEGER w = 0;
  350.         LIST words = str.split( delims:" \t\n" );
  351.  
  352.         foreach( words:s ) {
  353.             width = s.length() * font.cellWidth;
  354.  
  355.             this.addGlyph( str:s, x0:x, yb:y, wd:width, ht:font.cellHeight, famStyle:font.famStyle );
  356.             x += width + font.cellWidth;
  357.             w++;
  358.  
  359.             if( w >= wpl ) {
  360.                 x = x0;
  361.                 y += font.cellHeight + font.interLineSpacing;
  362.                 w = 0;
  363.             }
  364.         }
  365.     }
  366. }
  367.